<template>
  <BaseWrap>
    <div class="table-content">
      <div ref="top-table" class="top-table">
        <div class="head" :style="topStyle">
          <table ref="thead-slot" border="1" class="table">
            <slot name="tHead" />
            <!-- <slot v-if="formData.length>0" name="tHead"/> -->
          </table>
        </div>

        <div class="fixed-left-head">
          <table border="1" class="table" height="100%">
            <tr style="height:40px">
              <slot name="thead-fixed-left" />
            </tr>
          </table>
        </div>

        <div class="fixed-right-head">
          <table border="1" class="table" height="100%">
            <tr style="height:40px">
              <slot name="thead-fixed-right" />
            </tr>
          </table>
        </div>
      </div>

      <div ref="bottom-table" class="bottom-table">
        <div ref="container" class="container" :style="containerStyle">
          <div ref="scroll-wrapper" :style="paddingStyle">
            <table border="1" class="table">
              <BaseTr
                v-for="(item, index) in scrollList"
                :key="index"
                :$index="index"
                :item="item"
                :style="trStyle(item)"
                @click.native="selectRowAction(item)"
              >
                <slot name="tbody" />
              </BaseTr>
            </table>
          </div>
        </div>

        <div class="fixed-left-table" :style="fixedLeftTableStyle">
          <table border="1" class="table">
            <BaseTr
              v-for="(item, index) in scrollList"
              :key="`${index}_tbody_left_fixed`"
              :$index="index"
              :item="item"
              :style="trStyle(item)"
              @click.native="selectRowAction(item)"
            >
              <slot name="tbody-fixed-left" />
            </BaseTr>
          </table>
        </div>

        <div class="fixed-right-table" :style="fixedRightTableStyle">
          <table border="1" class="table">
            <BaseTr
              v-for="(item, index) in scrollList"
              :key="`${index}_tbody_right_fixed`"
              :$index="index"
              :item="item"
              :style="trStyle(item)"
              @click.native="selectRowAction(item)"
            >
              <slot name="tbody-fixed-right" />
            </BaseTr>
          </table>
        </div>
      </div>

      <div v-if="formData.length === 0" class="empty">
        <span>暂无数据</span>
      </div>
    </div>
  </BaseWrap>
</template>
<script>
export default {
  props: {
    formData: {
      default: () => [],
      type: Array
    },
    itemHeight: {
      default: '40',
      type: String
    },
    isCompare: {
      default: false,
      type: Boolean
    }
  },
  provide() {
    return {
      virtual: this.theadList
    }
  },
  data() {
    return {
      startIndex: 0,
      endIndex: 0,
      paddingTop: 0,
      paddingBottom: 0,
      allHeight: 0,
      containerInitHeight: 0, // 首次渲染的高度是height:100%的高度
      containerEndHeight: 0, // 首次渲染高度 ==》 视口范围可容纳行数 ==》最终的高度 (视口范围最佳显示行数)
      emptyContainerWidth: 0,
      maxItem: 0, // 视口范围内显示的最大行数(视口高度 / 每行规定的高度 + 1)
      scrollLeft: 0,
      scrollList: [], // 视口范围内实际加载的数据
      selectRow: -1, // 选中的行
      copyTableData: [],
      filterData: {},
      theadList: [],
      lastMsg: null
    }
  },
  computed: {
    containerStyle() {
      return {
        height: this.containerEndHeight + 'px'
      }
    },
    emptyContainerStyle() {
      return {
        width: this.emptyContainerWidth + 'px'
      }
    },
    fixedLeftTableStyle() {
      return {
        height: this.containerEndHeight - 18 + 'px'
      }
    },
    fixedRightTableStyle() {
      return {
        height: this.containerEndHeight - 18 + 'px'
      }
    },
    paddingStyle() {
      return {
        paddingTop: this.paddingTop + 'px',
        paddingBottom: this.paddingBottom + 'px',
        width: this.formData.length === 0 ? this.emptyContainerWidth + 'px' : 'auto',
        height: this.formData.length === 0 ? '100%' : 'auto'
      }
    },
    topStyle() {
      return {
        transform: `translateX(${-this.scrollLeft}px) translateZ(0)`
      }
    },
    trStyle() {
      return item => {
        return {
          background: this.selectRow === item.rowNo ? '#F5F7FA' : '#fff'
        }
      }
    }
  },

  watch: {
    formData: {
      handler: function() {
        this.copyTableData = this.$deepCopy(this.formData)
      }
    },
    copyTableData: {
      handler: function() {
        const len = this.copyTableData.length
        this.allHeight = len * Number(this.itemHeight)
        if (!this.paddingBottom) {
          this.paddingBottom = this.allHeight - this.scrollList.length * this.itemHeight
        }
        this.scrollList = this.copyTableData.slice(this.startIndex, this.endIndex)
        this.initTable()
        this.sendMsgToHeadCell()
      }
    },
    startIndex: {
      handler: function() {
        this.scrollList = this.copyTableData.slice(this.startIndex, this.endIndex)
      }
    }
  },
  mounted() {
    this.initTable()
    window.addEventListener('click', this.clickTableHandler)
    window.addEventListener('resize', this.initTable)
  },
  updated() {
    this.getTHead()
  },
  beforeDestroy() {
    window.removeEventListener('click', this.clickTableHandler)
    window.removeEventListener('resize', this.initTable)
  },
  methods: {
    // 初始化
    initTable() {
      this.$nextTick(() => {
        const topTable = this.$refs['top-table']
        const bottomTable = this.$refs['bottom-table']
        const container = this.$refs.container

        this.containerInitHeight = bottomTable.clientHeight

        // 空数据的状态下，撑开container内部的表格，目的是可以拖动滚动条查看表头
        if (this.formData.length === 0) {
          this.emptyContainerWidth = topTable.scrollWidth
        }

        this.maxItem = Math.floor(this.containerInitHeight / Number(this.itemHeight)) + 1
        this.containerEndHeight = (this.maxItem - 1) * this.itemHeight + 18
        if (this.containerEndHeight > this.containerInitHeight) {
          this.containerEndHeight = this.containerInitHeight
        }
        this.endIndex = this.maxItem
        this.scrollHandle(container, topTable)
        this.calculatePadding(container, topTable)
      })
    },
    scrollHandle(container, topTable) {
      container.addEventListener('scroll', e => {
        this.calculatePadding(container, topTable)
      })
    },

    // 计算
    calculatePadding(container, topTable) {
      const top = container.scrollTop
      this.scrollLeft = container.scrollLeft
      this.startIndex = Math.floor(top / Number(this.itemHeight))
      this.endIndex = this.startIndex + this.maxItem
      this.paddingTop = top
      if (this.endIndex >= this.copyTableData.length - 1) {
        this.paddingBottom = 18
        return
      }
      this.paddingBottom = this.allHeight - this.containerInitHeight - top
    },

    // 排序，永远根据已经filter之后的数据再排序（只做单列排序）
    sortAction(msg) {
      if (!msg) return
      this.lastMsg = msg
      const prop = msg.prop
      if (msg.sortIndex === 1) {
        this.copyTableData.sort((a, b) => {
          if (Object.prototype.toString.call(a[prop]) === '[object Number]') {
            return b[prop] - a[prop]
          } else {
            return b[prop].localeCompare(a[prop])
          }
        })
      } else {
        this.copyTableData.sort((a, b) => {
          if (Object.prototype.toString.call(a[prop]) === '[object Number]') {
            return a[prop] - b[prop]
          } else {
            return a[prop].localeCompare(b[prop])
          }
        })
      }
    },

    getTHead() {
      this.$nextTick(() => {
        const tableHead = this.$slots.tHead
        const arr = []
        for (const item1 of tableHead) {
          if (item1.children) {
            for (const item2 of item1.children) {
              if (item2.child) {
                if (item2.child.prop) {
                  arr.push({
                    prop: item2.child.prop,
                    width: item2.child.$el.clientWidth
                  })
                }
              }
            }
          }
        }
        this.theadList = arr
      })
    },
    // 通知thead子组件{
    sendMsgToHeadCell(isChange, current) {
      this.$nextTick(() => {
        const tableHead = this.$slots.tHead
        for (const item1 of tableHead) {
          if (item1.children) {
            for (const item2 of item1.children) {
              if (item2.child) {
                item2.child.getFiltersData(isChange, current)
              }
            }
          }
        }
      })
    },
    // 单列过滤数据重置
    filterReset(msg) {
      this.filterData[msg.prop] = []
      let filterEmpty = true
      for (const item in this.filterData) {
        if (this.filterData[item].length > 0) {
          filterEmpty = false
          break
        }
      }
      // 重置到最后一个 就重新初始化
      if (filterEmpty) {
        this.copyTableData = this.$deepCopy(this.formData)
      } else {
        this.filterCircle()
      }
      this.sortAction(this.lastMsg)
    },
    // 过滤数据
    filterAction(msg) {
      // 替换filterData 对应key下的筛选数据
      this.filterData[msg.prop] = msg.data
      this.filterCircle()
      this.sortAction(this.lastMsg)
    },
    // 遍历copyTableData 查找与筛选条件一致的数据
    filterCircle() {
      const arr = this.formData.filter(item => {
        for (const key in this.filterData) {
          const itemPorpList = this.filterData[key]
          if (itemPorpList.length === 0) continue
          if (itemPorpList.indexOf(item[key]) === -1) return false
        }
        return true
      })
      this.copyTableData = arr
    },
    // 清除所有过滤条件
    clearAllFilter() {
      this.filterData = {}
      this.copyTableData = this.$deepCopy(this.formData)
      const tableHead = this.$slots.tHead
      for (const item1 of tableHead) {
        if (item1.children) {
          for (const item2 of item1.children) {
            if (item2.child) {
              item2.child.checkList = []
            }
          }
        }
      }
      this.copyTableData = this.$deepCopy(this.formData)
      this.sortAction(this.lastMsg)
    },
    // 选中行变色
    selectRowAction(item) {
      this.selectRow = item.rowNo
    },
    // 点击table,选中行
    clickTableHandler(e) {
      // const pathArr = e.path.filter(item => item.className)
      // 冒泡的路径中如果不包含单元格组件则将selectRow重置为-1
      // pathArr.forEach(item => {
      //   if (item.className.indexOf('base-cell') < 0) {
      //   }
      // })
      // if (!pathArr.indexOf('base-cell')) {
      //   this.selectRow = -1
      // }
    }
  }
}
</script>
<style lang="scss" scoped>
.table-content {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  position: relative;
}

.table {
  width: 100%;
  border-collapse: collapse;
  border-color: #fff;
  border: none;
}

.top-table {
  width: calc(100% - 18px);
  position: relative;
  overflow-x: hidden;
  .fixed-left-head {
    position: absolute;
    top: 0px;
    left: 0px;
    height: 80px;
  }
  .fixed-right-head {
    position: absolute;
    top: 0;
    right: 0;
    height: 80px;
  }
}
.bottom-table {
  position: absolute;
  top: 80px;
  bottom: 0px;
  left: 0px;
  right: 0px;
  overflow-y: hidden;
  .container {
    width: 100%;
    height: 100%;
    overflow-y: scroll;
    overflow-x: scroll;
  }
  .fixed-left-table {
    position: absolute;
    top: 0;
    left: 0;
    // bottom: 27px;
    // bottom: 16px;
    overflow: hidden;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.12);
  }
  .fixed-right-table {
    position: absolute;
    top: 0;
    right: 18px;
    // bottom: 27px;
    bottom: 16px;
    overflow: hidden;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.12);
  }
}

.empty {
  position: absolute;
  top: 0;
  bottom: 80px;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  > span {
    color: #606266;
    font-size: 16px;
    transform: translateY(30px);
  }
}
</style>
